﻿using System;
using System.Linq;
using BusinessBingo.Data.DataLoadOptions;
using BusinessBingo.Data.Filter;
using BusinessBingo.Data.Interfaces;
using BusinessBingo.Model;
using BusinessBingo.Model.Interfaces;
using BusinessBingo.Queries;
using BusinessBingo.QueryHandlers.Base;
using BusinessBingo.QueryHandlers.Interfaces;
using BusinessBingo.QueryHandlers.Results;

namespace BusinessBingo.QueryHandlers
{
    public class GetBingoSetQueryHandler : BaseQueryHandler, IGetBingoSetQueryHandler
    {
        private ICheckIfBingoSetIsFinishedQueryHandler _checkIfBingoSetIsFinishedQuery;
        private IBingoSetRepository _bingoSetRepository;

        public GetBingoSetQueryHandler(
            ICheckIfBingoSetIsFinishedQueryHandler checkIfBingoSetIsFinishedQuery,
            IValidationState validationState,
            IBingoSetRepository bingoSetRepository) : base(validationState)
        {
            this._checkIfBingoSetIsFinishedQuery = checkIfBingoSetIsFinishedQuery;
            this._bingoSetRepository = bingoSetRepository;
        }

        public GetBingoSetQueryHandlerResult Execute(GetBingoSetQuery getBingoSetQuery)
        {
            GetBingoSetQueryHandlerResult result = new GetBingoSetQueryHandlerResult();

            if(getBingoSetQuery == default(GetBingoSetQuery))
                throw new ArgumentNullException("GetBingoSetQuery");

            if(getBingoSetQuery.UserId == default(Guid))
                this._validationState.AddError<GetBingoSetQuery>(x => x.UserId, ErrorTypes.Empty);

            if (getBingoSetQuery.GameId == default(Guid))
                this._validationState.AddError<GetBingoSetQuery>(x => x.GameId, ErrorTypes.Empty);

            if (this._validationState.IsValid == false) return result;

            BingoSetFilter filter = new BingoSetFilter();
            filter.WithUserId = getBingoSetQuery.UserId;
            filter.WithGameId = getBingoSetQuery.GameId;

            BingoSetDataLoadOptions dlo = new BingoSetDataLoadOptions();
            dlo.LoadWithWordPositions = true;

            BingoSet bingoSet = this._bingoSetRepository.GetItems(dlo, null, filter).Single();

            CheckIfBingoSetIsFinishedQuery checkIfBingoSetIsFinishedQuery = new CheckIfBingoSetIsFinishedQuery(bingoSet);
            
            CheckIfBingoSetIsFinishedQueryHandlerResult checkIfBingoSetIsFinishedQueryResult =
                this._checkIfBingoSetIsFinishedQuery.Execute(checkIfBingoSetIsFinishedQuery);

            if (checkIfBingoSetIsFinishedQueryResult.Succeeded == false)
                return result;

            bingoSet.IsFinished = checkIfBingoSetIsFinishedQueryResult.IsFinished;

            result.Succeeded = true;
            result.BingoSet = bingoSet;

            return result;
        }
    }
}